home *** CD-ROM | disk | FTP | other *** search
- /****************************************************************************
- *
- * AERCoreSuite.c
- *
- * AppleEvent Registry (AER) Core suite support
- *
- ****************************************************************************/
-
- #include <string.h> // for memset()
-
- #include "AERCoreSuite.h"
-
- #include "AppleEvent.h"
-
- // dispatch core events to objects of the appropriate object type
-
- #include "OSLClassApplication.h"
- #include "OSLClassDocument.h"
- #include "OSLClassWindow.h"
- #include "OSLClassGraphicObject.h"
-
- #include "OSLHelpers.h"
-
- /* ============================================================================
- Theory of Operation:
-
- The Core Suite is handled using the "object-first" method, described in
- Richard Clark's article in develop: "Apple Event Objects and You"
-
- The short story is that we install a single event handler to receive all
- events from the kAECoreSuite class of the Core Suite. There are object accessors
- for each class that is defined in the Core Suite, including Application, Document,
- GraphicObject, and Window.
-
- The AECoreSuiteEventHandler event handler is installed with a typeWildCard event ID
- so that all events in the Core suite, except Make (CreateElement) are passed to it.
- Make has its own handler because it doesn't receive its ospec in the direct
- parameter, unlike all the other events.
-
- AECoreSuiteEventHandler first calls AEResolve() to find out what type of object
- is in the direct parameter and to resolve a token for that object.
-
- AECoreSuiteEventHandler then passes the token, the original event, and the reply on to
- the event dispatcher for the type of object found in the direct parameter.
- Each object's event dispatcher then extracts the eventID from the apple event and
- passes the token on to the object's handler for that event. The handler for the
- object/event combination does the real work of manipulating the program's data and
- stuffs the result into the reply parameter.
-
- ============================================================================ */
-
- extern pascal OSErr AEObjectInit(void);
-
- static pascal OSErr AECoreSuiteEventHandler (AppleEvent *message, AppleEvent *reply, long refcon);
- static pascal OSErr AECreateElementEventHandler (AppleEvent *message, AppleEvent *reply, long refcon);
-
- // ---------------------------------------------------------------------------------------
-
- void
- InitCoreTokenRecord(CoreTokenRecord *token)
- {
- memset(token, '\0', sizeof(CoreTokenRecord));
- token->propertyCode = typeNull;
- }
-
- /*****************************************************************************
- *
- * InstallCoreSuiteHandlers()
- *
- * The event handler gets ALL events for the core suite
- *
- * The accessor functions are used by AEResolve() to construct tokens
- * for the object in the direct parameter of the core suite events.
- *
- *****************************************************************************/
-
- Boolean
- InstallCoreSuiteHandlers(void)
- {
- Boolean error = AEObjectInit() ;
-
- // Install event handlers for all StandardSuite (kAECoreSuite) events except Make (CreateElement)
-
- if (error == noErr)
- error = AEInstallEventHandler(kAECoreSuite,
- typeWildCard,
- NewAEEventHandlerProc(AECoreSuiteEventHandler),
- 0,
- false);
-
- // Special handler for StandardSuite Make (CreateElement) event
-
- if (error == noErr)
- error = AEInstallEventHandler(kAECoreSuite,
- kAECreateElement,
- NewAEEventHandlerProc(AECreateElementEventHandler),
- 0,
- false);
-
- // Install object accessors for each class we support
-
- if (error == noErr)
- error = InstallApplicationAccessors(); // Application
-
- if (error == noErr)
- error = InstallDocumentAccessors(); // Document
-
- if (error == noErr)
- error = InstallWindowAccessors(); // Window
-
- if (error == noErr)
- error = InstallGraphicObjectAccessors(); // Graphic Object
-
- // Install a generic handler to get a property from a typeAEList of tokens
-
- if (error == noErr)
- error = AEInstallObjectAccessor(cProperty, typeAEList, NewOSLAccessorProc(PropertyTokenFromAEListOfTokens), 0L, false);
-
- return (error == noErr);
- }
-
- // ---------------------------------------------------------------------------------------
- // This handler receives ALL core suite events EXCEPT Make (CreateElement)
- // and passes them on to the correct object dispatcher:
- // cApplication, cDocument, cFile, cGraphicObject, and cWindow.
- // Make (CreateElement) is different because it passes its ospec in the
- // insertionLoc parameter instead of in the direct object parameter.
-
- static pascal OSErr
- AECoreSuiteEventHandler(AppleEvent *appleEvent, AppleEvent *reply, long refcon)
- {
- OSErr error = noErr;
- OSErr ignoreError;
- OSErr eventError = noErr;
-
- Boolean objectResolved = true;
-
- AEDesc directParameter = {typeNull, nil}; // this is a ospec for the core suite
- AEDesc token = {typeNull, nil}; // this is filled in by AEResolve()
-
- DescType tokenType = typeNull;
- DescType dispatchClass = typeNull;
-
- long numItems;
-
- // extract the direct parameter (an object specifier)
-
- error = AEGetKeyDesc(appleEvent,
- keyDirectObject,
- typeWildCard,
- &directParameter);
- if (error != noErr)
- goto CleanUp;
-
- // check for null descriptor, which AEResolve doesn't handle well
- // If it's not null, then AEResolve will return an application-defined token
-
- if (directParameter.descriptorType == typeNull)
- {
- token = directParameter;
- }
- else {
- // The direct parameter contains an object specifier, or an "reference" in
- // AppleScript terminology, such as "rectangle 1 of document 1".
- // AEResolve() will recursively call our installed object accessors
- // until it returns a token with data referencing the requested object.
-
- error = AEResolve(&directParameter, kAEIDoMinimum, &token);
-
- }
-
- if (error == errAENoSuchObject || error == errAEIllegalIndex)
- {
- // If we were executing an "Exists..." appleevent, we can reply it here
- // because we have already determined that it DOES NOT exist.
- // First, we get the event ID. We use "eventError" instead of "error"
- // so that the result of AEGetAttributePtr() does not disturb the
- // errAENoSuchObject result previously returned.
-
- AEEventID eventID;
- OSType typeCode;
- Size actualSize = 0L;
- eventError = AEGetAttributePtr(appleEvent,
- keyEventIDAttr,
- typeType,
- &typeCode,
- (Ptr)&eventID, // Get the eventID from the AppleEvent
- sizeof(eventID),
- &actualSize);
-
- // If event was an "Exists..." message, store the result (false) in the reply
- // because AEResolve() returned errAENoSuchObject.
-
- if (eventError == noErr && eventID == kAEDoObjectsExist)
- {
- Boolean foundIt = false;
- ignoreError = AEPutParamPtr(reply, keyAEResult, typeBoolean, (Ptr)&foundIt, sizeof(Boolean));
-
- // Now, we set the error to noErr so that the scripting component doesn't complain
- // that the object does not exist. We only do this if we were executing an "Exists..."
- // event. Otherwise, the errAENoSuchObject will be returned.
- error = noErr;
- }
-
- objectResolved = false;
- }
-
- if (objectResolved == false || error != noErr)
- goto CleanUp;
-
- // Pass the token returned by AEResolve(), and the original AppleEvent event and reply,
- // on to the appropriate object dispatcher
-
- // The token type is, by convention, the same as class ID that handles this event.
- // However, for property tokens, tokenType is cProperty for all objects, so
- // we look inside the token at its dispatchClass to find out which class of object
- // should really handle this AppleEvent.
-
- // Also, if the resolver returned a list of objects in the token,
- // the type will be typeAEList or one of our special list types, so
- // we set the dispatch class based on the list type
- // instead of on the type of the token itself
-
- if (TokenContainsTokenList(&token))
- {
- error = AECountItems(&token, &numItems);
-
- if (numItems == 0) // could be an empty list
- {
- dispatchClass = typeNull;
- }
- else
- {
- AEDesc tempToken = {typeNull, nil};
- error = GetFirstNonListToken((AEDesc *)&token, &tempToken);
- if (error == noErr && tempToken.descriptorType != typeNull)
- {
- dispatchClass = ExtractDispatchClassFromToken(&tempToken);
- }
- else
- {
- dispatchClass = typeNull;
- error = noErr;
- }
- AEDisposeDesc(&tempToken);
- }
- }
- else if (token.descriptorType == typeNull) // make sure we correctly handle things for cApplication that don't have a direct parameter
- {
- dispatchClass = typeNull;
- }
- else
- {
- dispatchClass = ExtractDispatchClassFromToken(&token);
- }
-
- if (dispatchClass == cFile)
- {
- AEEventID eventID = 0L;
- OSType typeCode = 0L;
- Size actualSize = 0L;
- eventError = AEGetAttributePtr(appleEvent,
- keyEventIDAttr,
- typeType,
- &typeCode,
- (Ptr)&eventID, // Get the eventID from the AppleEvent
- sizeof(eventID),
- &actualSize);
- }
-
- switch (dispatchClass)
- {
-
- case typeNull:
- case cApplication:
- error = ApplicationEventDispatcher(&token, appleEvent, reply, refcon);
- break;
-
- case cDocument:
- error = DocumentEventDispatcher(&token, appleEvent, reply, refcon);
- break;
-
- case cWindow:
- error = WindowEventDispatcher(&token, appleEvent, reply, refcon);
- break;
-
-
- // -----
- // Handles all Graphic Object subclasses
-
- case cGraphicObject:
- error = GraphicObjectEventDispatcher(&token, appleEvent, reply, refcon);
- break;
-
- default:
- error = errAEEventNotHandled;
- }
-
- CleanUp:
-
- AEDisposeDesc(&directParameter);
- AEDisposeDesc(&token);
-
- return error;
-
- }
-
- // ---------------------------------------------------------------------------------------
- // This handler receives the Core suite Make (CreateElement) event
- // and passes it on to the correct object dispatcher:
- // cApplication, cDocument, cFile, cGraphicObject, etc.
- // Make (CreateElement) is different than the other events processed above
- // because it passes its ospec in the insertionLoc parameter instead of
- // in the direct object parameter.
-
- static pascal OSErr
- AECreateElementEventHandler(AppleEvent *appleEvent, AppleEvent *reply, long refcon)
- {
-
- OSErr error = noErr;
- AEDesc token = {typeNull, nil};
- DescType dispatchClass = typeNull;
-
- // Extract the type of object we want to create.
- // We use this to call the event dispatcher for that kind of objects
-
- error = AEGetParamDesc(appleEvent,
- keyAEObjectClass, // class of object to create
- typeType,
- &token);
- if (error != noErr)
- goto CleanUp;
-
- dispatchClass = **(DescType **)(token.dataHandle);
-
- switch (dispatchClass) {
-
- // -----
- // Application, document, and windows each have their own event dispatchers
-
- case typeNull:
- case cApplication:
- error = ApplicationEventDispatcher(&token, appleEvent, reply, refcon);
- break;
-
- case cDocument:
- error = DocumentEventDispatcher(&token, appleEvent, reply, refcon);
- break;
-
- case cWindow:
- error = WindowEventDispatcher(&token, appleEvent, reply, refcon);
- break;
-
- // -----
- // All graphic objects are handled by cGraphicObject event dispatcher
-
- case cGraphicLine:
- case cGroupedGraphic:
- case cGraphicObject:
- case cOval:
- case cPolygon:
- case cRectangle:
- case cRoundedRectangle:
- error = GraphicObjectEventDispatcher(&token, appleEvent, reply, refcon);
- break;
-
- default:
- error = errAEEventNotHandled;
- }
-
- CleanUp:
-
- AEDisposeDesc(&token);
-
- return error;
-
- }
-
-
- //----------------------------------------------------------------------------------
- // Handler to get a property from a typeAEList of tokens
- //----------------------------------------------------------------------------------
-
- pascal OSErr
- PropertyTokenFromAEListOfTokens( DescType desiredClass,
- const AEDesc* containerToken,
- DescType containerClass,
- DescType keyForm,
- const AEDesc* keyData,
- AEDesc* resultToken,
- long refCon)
- {
- OSErr error = noErr;
-
- switch (containerClass)
- {
- case cGraphicObject:
- case cOval:
- case cPolygon:
- case cRectangle:
- case cRoundedRectangle:
- case cGraphicLine:
- case cGroupedGraphic:
- error = PropertyFromGraphicObjectAccessor(desiredClass,
- containerToken,
- containerClass,
- keyForm,
- keyData,
- resultToken,
- refCon);
- break;
-
-
- case cWindow:
- error = PropertyFromWindowAccessor(desiredClass,
- containerToken,
- containerClass,
- keyForm,
- keyData,
- resultToken,
- refCon);
- break;
-
-
- case cDocument:
- error = PropertyFromDocumentAccessor(desiredClass,
- containerToken,
- containerClass,
- keyForm,
- keyData,
- resultToken,
- refCon);
- break;
-
-
- // ••• ADD OTHER CLASSES HERE, FOR COMPLETNESS
- // •••
-
- default:
- error = errAEEventNotHandled;
- break;
- }
-
- return error;
- }
-
- // ---------------------------------------------------------------------------------------
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-